package com.atguigu.gulimall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.es.SkuEsModel;
import com.atguigu.common.to.SkuReductionTo;
import com.atguigu.common.to.SkuStockTo;
import com.atguigu.common.to.SpuBoundsTo;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.feign.CouponFeignService;
import com.atguigu.gulimall.product.feign.EsFeignService;
import com.atguigu.gulimall.product.feign.WareFeignService;
import com.atguigu.gulimall.product.service.*;
import com.atguigu.gulimall.product.vo.*;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Service("spuInfoService")
@Slf4j
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    SpuInfoDescService spuInfoDescService;

    @Autowired
    SpuImagesService spuImagesService;

    @Autowired
    ProductAttrValueService productAttrValueService;

    @Autowired
    SkuInfoService skuInfoService;

    @Autowired
    SkuImagesService skuImagesService;

    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    CouponFeignService couponFeignService;

    @Autowired
    BrandService brandService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    AttrService attrService;

    @Autowired
    WareFeignService wareFeignService;

    @Autowired
    EsFeignService esFeignService;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }


    @Transactional
    @Override
    public void saveSpuInfo(SpuSaveVo spuSaveVo) {
        //1. 保存spu的基本信息 pms_spu_info

        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuSaveVo, spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        this.save(spuInfoEntity);
        Long spuId = spuInfoEntity.getId();
        //2.保存spu的描述图片:pms_spu_info_desc
        List<String> decript = spuSaveVo.getDecript();
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setSpuId(spuId);
        //以逗号分割每一个元素
        String join = String.join(",", decript);
        spuInfoDescEntity.setDecript(join);
        spuInfoDescService.save(spuInfoDescEntity);

        //3.保存spu的图片集
        spuImagesService.saveSpuImages(spuId, spuSaveVo.getImages());
        //先获取所有的图片
        //保存图片的时候 并且保存是哪个spu的图片

        //4.保存spu的规格属性  pms_product_attr_value
        List<BaseAttrs> baseAttrs = spuSaveVo.getBaseAttrs();
        productAttrValueService.saveSpuAttrValues(spuId, baseAttrs);


        //保存商品spu的积分设置
        Bounds bounds = spuSaveVo.getBounds();
        SpuBoundsTo spuBoundsTo = new SpuBoundsTo();
        BeanUtils.copyProperties(bounds, spuBoundsTo);
        spuBoundsTo.setSpuId(spuId);
        //调用远程服务接口进行保存
        R res = couponFeignService.save(spuBoundsTo);
        if (res.getCode() != 0) {
            log.error("调用远程服务保存spu积分设置失败");
        }

        //5.保存当前spu对应的sku的信息(sku的所有信息保存在skus中)
        List<Skus> skus = spuSaveVo.getSkus();
        skus.forEach(sku -> {
            //选取默认图片
            List<Images> images = sku.getImages();
            String defaultImgUrl = "";
            for (Images image : images) {
                if (image.getDefaultImg() == 1) {
                    defaultImgUrl = image.getImgUrl();
                }
            }
            //5.1)、sku的基本信息:pms_sku_info
            SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
            //    private String skuName;
            //    private BigDecimal price;
            //    private String skuTitle;
            //    private String skuSubtitle;
            BeanUtils.copyProperties(sku, skuInfoEntity);
            skuInfoEntity.setSpuId(spuId);
            skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
            skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
            skuInfoEntity.setSaleCount(0L);
            //默认图片
            skuInfoEntity.setSkuDefaultImg(defaultImgUrl);
            skuInfoService.save(skuInfoEntity);

            Long skuId = skuInfoEntity.getSkuId();
            //5.2)、sku的图片信息:pms_sku_images
            //ToDO:过滤掉图片地址没有的记录
            List<SkuImagesEntity> collect = images.stream().filter(item -> {
                return !StringUtils.isEmpty(item.getImgUrl());
            }).map(img -> {
                SkuImagesEntity imagesEntity = new SkuImagesEntity();
                imagesEntity.setSkuId(skuId);
                BeanUtils.copyProperties(img, imagesEntity);
                return imagesEntity;
            }).collect(Collectors.toList());
            skuImagesService.saveBatch(collect);

            //5.3)、sku的销售属性信息: pms_sku_sale_attr_value
            List<Attr> attr = sku.getAttr();
            List<SkuSaleAttrValueEntity> attrValueEntityList = attr.stream().map(attr1 -> {
                SkuSaleAttrValueEntity attrValueEntity = new SkuSaleAttrValueEntity();
                attrValueEntity.setSkuId(skuId);
                BeanUtils.copyProperties(attr1, attrValueEntity);
                return attrValueEntity;
            }).collect(Collectors.toList());
            //批量保存
            skuSaleAttrValueService.saveBatch(attrValueEntityList);

            //5.4)、sku的优惠、满减等信息；（远程服务）
            SkuReductionTo skuReductionTo = new SkuReductionTo();
//            skuReductionTo.setMemberPrice(sku.getMemberPrice());
            skuReductionTo.setSkuId(skuId);
            BeanUtils.copyProperties(sku, skuReductionTo);
            R r = couponFeignService.saveSkuInfo(skuReductionTo);
            if (r.getCode() != 0) {
                log.error("调用远程服务保存满减信息失败");
            }


        });
    }


    @Override
    public PageUtils queryByCondition(Map<String, Object> params) {
        //检索值(模糊查询)
        String key = (String) params.get("key");
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(key)) {
            wrapper.eq("id", key).or().like("spu_name", key);
        }

        //分类名称
        String catalog_id = (String) params.get("catelogId");
//        Long catalog_id = (long) params.get("catalog_id");
        if (!StringUtils.isEmpty(catalog_id)) {
            wrapper.eq("catalog_id", catalog_id);
        }
        //品牌名称
//        Long brand_id = (Long) params.get("brand_id");
        String brand_id = (String) params.get("brandId");
        if (!StringUtils.isEmpty(brand_id)) {
            wrapper.eq("brand_id", brand_id);
        }
        //商品状态
//        Integer status = (Integer) params.get("status");
        String status = (String) params.get("status");
        if (!StringUtils.isEmpty(status)) {
            wrapper.eq("publish_status", status);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);


    }


    /**
     * 商品上架
     *
     * @param spuId
     */
    @Override
    public void up(Long spuId) throws IOException {
        //1.根据spuId查出所有的Sku商品
        QueryWrapper<SkuInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("spu_id", spuId);
        List<SkuInfoEntity> entityList = skuInfoService.list(wrapper);
        //接受远程库存服务返回的结果
        Map<Long, Boolean> stockMap = null;
        try {
            List<Long> skuIdList = entityList.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
            //TODO 1、发送远程调用，查询库存系统是否有库存  因为有多个SkuId，所以只调用一次远程服务比较好
//            R<List<SkuStockTo>> stock = wareFeignService.hashStock(skuIdList);
            R r = wareFeignService.hashStock(skuIdList);
            //设置要获取的类型
            TypeReference<List<SkuStockTo>> reference = new TypeReference<List<SkuStockTo>>() {
            };
            List<SkuStockTo> skuStockToList = r.getData(reference);
            //拿到远程调用的结果
            //收集成Map。Key=skuId,value=hashStock
            stockMap = skuStockToList.stream().collect(Collectors.toMap(SkuStockTo::getSkuId, SkuStockTo::getHasStock));
        } catch (Exception e) {
            //这里catch住的原因为为了高可用。防止因为网络抖动等原因导致的远程调用失败而导致全局的业务失败
            log.error("调用库存远程服务出现异常:{}", e);
        }


        //TODO: 4、查询当前Spu的所有属性
        List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
        //过滤出编号
        List<Long> attrIdsList = productAttrValueEntities.stream().map(productAttrValueEntity -> {
            return productAttrValueEntity.getAttrId();
        }).collect(Collectors.toList());
        //过滤出属性为可检索的项
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("attr_id", attrIdsList).eq("search_type", "1");
        List<AttrEntity> attrEntities = attrService.list(queryWrapper);
        //满足可检索的属性编号
        List<Long> searchIDs = attrEntities.stream().map(attrEntity -> {
            return attrEntity.getAttrId();
        }).collect(Collectors.toList());

        //查询出Es模型中的Attrs
        List<SkuEsModel.Attr> attrs = new ArrayList<>();

        List<ProductAttrValueEntity> collect = productAttrValueEntities.stream().filter(productAttrValueEntity -> {
            return searchIDs.contains(productAttrValueEntity.getAttrId());
        }).collect(Collectors.toList());
        System.out.println("收集到的集合为:" + collect);

        for (ProductAttrValueEntity productAttrValueEntity : collect) {
            SkuEsModel.Attr attr = new SkuEsModel.Attr();
            BeanUtils.copyProperties(productAttrValueEntity, attr);
            attrs.add(attr);
        }


        System.out.println("收集到的Attrs的List为:" + attrs);

        productAttrValueEntities.stream().filter(productAttrValueEntity -> {
            return searchIDs.contains(productAttrValueEntity.getAttrId());
        }).map(productAttrValueEntity -> {
            SkuEsModel.Attr attr = new SkuEsModel.Attr();
            BeanUtils.copyProperties(productAttrValueEntity, attr);
            attrs.add(attr);
            return attr;
        });


        //组装数据
        Map<Long, Boolean> finalStockMap = stockMap;
        List<SkuEsModel> skuEsModels = entityList.stream().map(skuInfoEntity -> {
            //es中存储的模型
            SkuEsModel esModel = new SkuEsModel();
            BeanUtils.copyProperties(skuInfoEntity, esModel);
            esModel.setSkuPrice(skuInfoEntity.getPrice());
            esModel.setSkuImg(skuInfoEntity.getSkuDefaultImg());

            //设置库存
            esModel.setHasStock(finalStockMap == null ? false : finalStockMap.get(skuInfoEntity.getSkuId()));


            //TODO 2、热度评分(默认为0)
            esModel.setHotScore(0L);
            //TODO 3、查询品牌和分类的信息
            BrandEntity brandEntity = brandService.getById(esModel.getBrandId());
            esModel.setBrandImg(brandEntity.getLogo());
            esModel.setBrandName(brandEntity.getName());

            CategoryEntity categoryEntity = categoryService.getById(esModel.getCatalogId());
            esModel.setCatalogName(categoryEntity.getName());

            //设置属性
            esModel.setAttrs(attrs);


            return esModel;
        }).collect(Collectors.toList());

        //发送给Es服务进行保存
        R r = esFeignService.savaIndex(skuEsModels);
        if (r.getCode() != 0) {
            log.error("调用es进行保存上架数据失败");
        } else {
            //修改当前spu的状态为已上架
            SpuInfoEntity infoEntity = new SpuInfoEntity();
            infoEntity.setId(spuId);
            infoEntity.setPublishStatus(1);
            infoEntity.setUpdateTime(new Date());
            baseMapper.updateById(infoEntity);
        }


    }


    @Override
    public SpuInfoEntity getbySkuId(long skuId) {
        SkuInfoEntity skuInfoEntity = skuInfoService.getById(skuId);
        Long spuId = skuInfoEntity.getSpuId();
        SpuInfoEntity spuInfoEntity = baseMapper.selectById(spuId);
        return spuInfoEntity;
    }


}